package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Autowired
	private TrackInfoFeignClient trackInfoFeignClient;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;


	@Override
	public Map<String, Object> wxLogin(String code) {
		WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
		//调用微信登陆api
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
		//openid:每个人的微信都对应一个唯一标识
		String openid = wxMaJscode2SessionResult.getOpenid();
		//利用openid实现登录或注册功能；
		UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId,openid));
		//判断是否为空
		if(null == userInfo){
			//说明要注册
			userInfo = new UserInfo();
			userInfo.setWxOpenId(openid);
			userInfo.setNickname("书友："+System.currentTimeMillis());
			userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
			//保存数据到数据库
			userInfoMapper.insert(userInfo);
			//需要给当前注册的用户进行初始化充值，这里选择mq异步操作：防止因为初始化失败导致用户注册失败，导致用户跑路，确保完整盗取用户信息
			//防止因为初始化失败导致注册失败
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_USER_REGISTER,userInfo.getId());
		}
		//说明要登陆：将数据存储到redis和返回的token中
		String token = UUID.randomUUID().toString().replaceAll("-","");
		String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX+token;
		redisTemplate.opsForValue().set(userLoginKey,userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);

		HashMap<String,Object> map = new HashMap<>();
		map.put("token",token);
        return map;
	}

	@Override
	public UserInfoVo getUserInfoVoByUserId(Long userId) {
		//获取到用户信息对象
		UserInfo userInfo = this.getById(userId);
		//创建UserInfo对象
		UserInfoVo userInfoVo = new UserInfoVo();
		//属性拷贝
		BeanUtils.copyProperties(userInfo,userInfoVo);
		return userInfoVo;
	}

	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
		//创建map集合
		Map<Long,Integer> map = trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 0));
		//判断用户是否购买过专辑：user_paid_album
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId,userId).eq(UserPaidAlbum::getAlbumId,albumId));
		if(null != userPaidAlbum){
			//当前用户购买声了专辑
			return trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
		}
		//查询用户购买声音得集合列表
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList((new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId,userId).in(UserPaidTrack::getTrackId,trackIdList)));
		//这个列表有可能是空
		if(!CollectionUtils.isEmpty(userPaidTrackList)){
			//购买过声音
			for(UserPaidTrack userPaidTrack:userPaidTrackList){
				map.put(userPaidTrack.getTrackId(),1);
			}
		}
		return map;
	}

	@Override
	public Boolean isPaidAlbum(Long userId, Long albumId) {
		//查看当前用户是否购买过专辑
		//先判断用户Id是否相同，在判断专辑Id是否相同
		return null != userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId,userId).eq(UserPaidAlbum::getAlbumId,albumId));
	}

	@Override
	public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
		//用户购买的声音列表
		List<Long> userPaidTrackList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId,userId)
				.eq(UserPaidTrack::getAlbumId,albumId))
				.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
		//返会用户购买的声音列表
		return userPaidTrackList;
	}

	@Override
	public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
		//记录用户购买信息
		if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())){
			//购买专辑 user_paid_album
			UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId()).eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0)));
			//判断
			if(null != userPaidAlbum){
				return;
			}
			//创建对象保存数据
			userPaidAlbum = new UserPaidAlbum();
			//赋值
			userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
			userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
			userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
			//保存数据
			userPaidAlbumMapper.insert(userPaidAlbum);
		}else if(SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())){
			//声音user_paid_track;判断当前购买的声音Id再当前表中是否存在
			//用户要购买的声音列表
			List<Long> itemIdList = userPaidRecordVo.getItemIdList();
			//用户已购买的声音列表
			LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(UserPaidTrack::getUserId,userPaidRecordVo.getUserId())
					.in(UserPaidTrack::getTrackId,itemIdList);
			//用户在已购买的列表中买了对应的声音
			List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
			//需要讲这个集合变为set集合，通过trackId判断是否存在
			Set<Long> paidTrackIdSet = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toSet());
			//判断
			if(!CollectionUtils.isEmpty(paidTrackIdSet)){
				//有买过
				for(Long itemId:itemIdList){
					if(paidTrackIdSet.contains(itemId)){
						continue;
					}
				}
			}
			//根据声音Id获取声音对象
			Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0));
			Assert.notNull(trackInfoResult,"查询声音信息失败");
			TrackInfo trackInfo =trackInfoResult.getData();
			Assert.notNull(trackInfo,"查询声音信息失败");
			//没有买过
			for(Long trackId : itemIdList){
				//创建一个对象；
				UserPaidTrack userPaidTrack = new UserPaidTrack();
				userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
				userPaidTrack.setUserId(userPaidRecordVo.getUserId());
				userPaidTrack.setAlbumId(trackInfo.getAlbumId());
				userPaidTrack.setTrackId(trackId);
				//保存数据
				userPaidTrackMapper.insert(userPaidTrack);
			}
		}else {
			//购买Vip；user_vip_service  可能需要续期
			//获取到购买时长：vip_service_config.id
			Long vipServiceId = userPaidRecordVo.getItemIdList().get(0);
			VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceId);
			Integer serviceMonth = vipServiceConfig.getServiceMonth();
			//保存数据
			UserVipService userVipService = new UserVipService();
			//赋值
			userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
			userVipService.setUserId(userPaidRecordVo.getUserId());
			Date currentTime = new Date();
			userVipService.setCreateTime(currentTime);
			//过期时间，第一种情况：第一次购买，第二种情况：续期
			//判断当前用户是否是VIP并且未过期，续期
			UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
			if(userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(currentTime)){
				currentTime = userInfo.getVipExpireTime();
			}
			//创建对象
			LocalDateTime localDateTime = new LocalDateTime(currentTime);
			//获取过期时间
			Date expireTime = localDateTime.plusMonths(serviceMonth).toDate();
			//设置过期时间
			userVipService.setExpireTime(expireTime);
			//保存Vip购买记录
			userVipServiceMapper.insert(userVipService);
			//修改Vip标识
			userInfo.setIsVip(1);
			userInfo.setVipExpireTime(expireTime);
			this.updateById(userInfo);
		}
	}
}
